'''
Author: chenxi
Date: 2025-08-03 02:17:27
LastEditors: chenxi
LastEditTime: 2025-08-03 02:18:27
FilePath: \gui_modules\file_processor.py
Description: 
Copyright 2025 OBKoro1, All Rights Reserved. 
2025-08-03 02:17:27
'''
import tkinter as tk
from tkinter import ttk, filedialog, messagebox  # 添加ttk导入
from datetime import datetime
from hex_loader import HexLoader
from bin_loader import BinLoader
import json

class FileProcessor:
    def __init__(self, root, message_display, timestamp_var):
        self.root = root
        self.message_display = message_display
        self.timestamp_var = timestamp_var
        self.hex_loader = None
        self.bin_loader = None

    def select_file(self):
        """选择文件并返回路径"""
        file_path = filedialog.askopenfilename(
            title="选择文件",
            filetypes=[("HEX/BIN files", "*.hex *.bin"), ("All files", "*.*")]
        )
        return file_path if file_path else None

    def load_hex_file(self, file_path):
        """加载HEX文件"""
        try:
            self.hex_loader = HexLoader(verify_checksum=False)
            if self.hex_loader.load_hex_file(file_path):
                info = self.hex_loader.get_file_info()
                self._display_file_info(info, "HEX")
                return True
        except Exception as e:
            messagebox.showerror("错误", f"加载HEX文件时发生错误:\n{str(e)}")
        return False

    def load_bin_file(self, file_path):
        """加载BIN文件"""
        try:
            self.bin_loader = BinLoader()
            if self.bin_loader.load_bin_file(file_path):
                info = self.bin_loader.get_file_info()
                self._display_file_info(info, "BIN")
                return True
        except Exception as e:
            messagebox.showerror("错误", f"加载BIN文件时发生错误:\n{str(e)}")
        return False

    def _display_file_info(self, file_info, file_type):
        """显示文件信息"""
        self.message_display.config(state=tk.NORMAL)
        
        if self.timestamp_var.get():
            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            self.message_display.insert(tk.END, f"[{timestamp}] ", "timestamp")
        
        self.message_display.insert(tk.END, f"{file_type}文件信息:\n", "server")
        self.message_display.insert(tk.END, f"  文件路径: {file_info['file_path']}\n")
        self.message_display.insert(tk.END, f"  文件大小: {file_info['file_size']} 字节\n")
        
        if file_type == "HEX":
            mem_info = self.hex_loader.get_memory_map_info()
            self.message_display.insert(tk.END, f"  段数量: {file_info['segments_count']}\n")
            self.message_display.insert(tk.END, f"  总字节数: {file_info['total_bytes']}\n")
            self.message_display.insert(tk.END, f"  地址范围: 0x{mem_info['min_address']:08X} - 0x{mem_info['max_address']:08X}\n")
        else:  # BIN
            mem_info = self.bin_loader.get_memory_info()
            self.message_display.insert(tk.END, f"  加载地址: 0x{file_info['load_address']:08X}\n")
            self.message_display.insert(tk.END, f"  内存大小: {file_info['memory_size']} 字节\n")
            self.message_display.insert(tk.END, f"  地址范围: 0x{mem_info['load_address']:08X} - 0x{mem_info['end_address']:08X}\n")
        
        self.message_display.insert(tk.END, "\n")
        self.message_display.config(state=tk.DISABLED)
        self.message_display.see(tk.END)

    def export_hex_to_bin(self, output_path):
        """导出HEX为BIN"""
        if not self.hex_loader or not self.hex_loader.memory_map:
            return False
        return self.hex_loader.export_to_bin(output_path)

    def export_bin_to_hex(self, output_path):
        """导出BIN为HEX"""
        if not self.bin_loader or not self.bin_loader.memory_data:
            return False
        return self.bin_loader.export_to_hex(output_path)

    def get_hex_info(self):
        """获取HEX文件信息"""
        if not self.hex_loader or not self.hex_loader.memory_map:
            return None
        return self.hex_loader.get_file_info()

    def get_bin_info(self):
        """获取BIN文件信息"""
        if not self.bin_loader or not self.bin_loader.memory_data:
            return None
        return self.bin_loader.get_file_info()
        
    def show_bin_content(self):
        """显示BIN文件内容"""
        if not self.bin_loader or not self.bin_loader.memory_data:
            messagebox.showwarning("警告", "没有加载BIN文件")
            return
            
        # 创建内容显示窗口
        content_window = tk.Toplevel(self.root)
        content_window.title("BIN文件内容")
        content_window.geometry("800x600")
        
        # 创建框架
        main_frame = ttk.Frame(content_window)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 创建标签显示文件信息
        info_frame = ttk.Frame(main_frame)
        info_frame.pack(fill=tk.X, pady=(0, 10))
        
        file_info = self.bin_loader.get_file_info()
        ttk.Label(
            info_frame, 
            text=f"文件: {file_info['file_path']} | 大小: {file_info['file_size']} 字节"
        ).pack(side=tk.LEFT)
        
        # 创建笔记本控件（标签页）
        notebook = ttk.Notebook(main_frame)
        notebook.pack(fill=tk.BOTH, expand=True)
        
        # 十六进制视图 - 确保框架填充整个空间
        hex_frame = ttk.Frame(notebook)
        notebook.add(hex_frame, text="十六进制")
        hex_frame.pack_propagate(False)  # 防止子组件改变框架大小
        hex_frame.config(width=780, height=500)  # 设置固定尺寸
        
        # ASCII视图 - 确保框架填充整个空间
        ascii_frame = ttk.Frame(notebook)
        notebook.add(ascii_frame, text="ASCII")
        ascii_frame.pack_propagate(False)  # 防止子组件改变框架大小
        ascii_frame.config(width=780, height=500)  # 设置固定尺寸
        
        # 填充十六进制视图
        self._create_hex_view(hex_frame)
        
        # 填充ASCII视图
        self._create_ascii_view(ascii_frame)
        
        # 添加诊断信息（开发完成后可移除）
        print(f"显示BIN内容窗口已创建，尺寸：{content_window.winfo_width()}x{content_window.winfo_height()}")
        print(f"十六进制标签页尺寸：{hex_frame.winfo_width()}x{hex_frame.winfo_height()}")
        print(f"ASCII标签页尺寸：{ascii_frame.winfo_width()}x{ascii_frame.winfo_height()}")

    def _create_hex_view(self, parent):
        """创建十六进制视图"""
        # 获取BIN文件数据
        data = self.bin_loader.memory_data
        if not data:
            return
            
        # 创建滚动条
        scrollbar = ttk.Scrollbar(parent)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建文本框 - 添加边框使其可见
        text = tk.Text(
            parent, 
            wrap=tk.NONE,
            font=("Consolas", 10),
            yscrollcommand=scrollbar.set,
            width=80,
            height=25,
            bd=2,  # 边框宽度
            relief=tk.SUNKEN  # 边框样式
        )
        text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        scrollbar.config(command=text.yview)
        
        # 设置文本为只读
        text.config(state=tk.NORMAL)
        
        # 每行显示16字节
        bytes_per_line = 16
        total_bytes = len(data)
        display_bytes = min(total_bytes, 1024)  # 只显示前1024字节防止卡顿
        
        for i in range(0, display_bytes, bytes_per_line):
            # 地址列
            text.insert(tk.END, f"{i:08X}: ")
            
            # 十六进制列
            chunk = data[i:i+bytes_per_line]
            hex_str = " ".join(f"{b:02X}" for b in chunk)
            
            # 填充空格使列对齐
            hex_str = hex_str.ljust(3 * bytes_per_line - 1)
            text.insert(tk.END, hex_str + "  ")
            
            text.insert(tk.END, "\n")
        
        # 添加分页信息
        if display_bytes < total_bytes:
            text.insert(tk.END, f"\n... 仅显示前{display_bytes}字节，共{total_bytes}字节 ...\n")
        
        text.config(state=tk.DISABLED)
        text.yview_moveto(0.0)  # 滚动到顶部
    
    def _create_ascii_view(self, parent):
        """创建ASCII视图"""
        # 获取BIN文件数据
        data = self.bin_loader.memory_data
        if not data:
            return
            
        # 创建滚动条
        scrollbar = ttk.Scrollbar(parent)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建文本框 - 添加边框使其可见
        text = tk.Text(
            parent, 
            wrap=tk.NONE,
            font=("Consolas", 10),
            yscrollcommand=scrollbar.set,
            width=80,
            height=25,
            bd=2,  # 边框宽度
            relief=tk.SUNKEN  # 边框样式
        )
        text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        scrollbar.config(command=text.yview)
        
        # 设置文本为只读
        text.config(state=tk.NORMAL)
        
        # 每行显示64个字符
        chars_per_line = 64
        total_bytes = len(data)
        display_bytes = min(total_bytes, 1024)  # 只显示前1024字节防止卡顿
        
        for i in range(0, display_bytes, chars_per_line):
            # 地址列
            text.insert(tk.END, f"{i:08X}: ")
            
            # ASCII列
            chunk = data[i:i+chars_per_line]
            ascii_str = "".join(chr(b) if 32 <= b <= 126 else "." for b in chunk)
            text.insert(tk.END, ascii_str)
            
            text.insert(tk.END, "\n")
        
        # 添加分页信息
        if display_bytes < total_bytes:
            text.insert(tk.END, f"\n... 仅显示前{display_bytes}字节，共{total_bytes}字节 ...\n")
        
        text.config(state=tk.DISABLED)
        text.yview_moveto(0.0)  # 滚动到顶部
